#include "EntriesManager.h"
EntriesManager* EntriesManager::_instance = NULL;
//EntriesManager* EntriesManager::getInstance(FileManager* stub) {

EntriesManager* EntriesManager::getInstance(FileManager* file) {
	if(_instance == NULL)
    {
		if(file == NULL){
			file = FileManager::getInstance(_fileName);
		}
		_instance = new EntriesManager(file);
        return _instance;
    }
    else
    {
        return _instance;
    }
}
EntriesManager::EntriesManager(FileManager* file): _file(file)
{
	_entries.activeEntries=_file->getEntries();//DEPENDENCY ON FILEMANAGER
	_entries.currentDisplayIndex=_entries.activeEntries.size();
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
	filterStatus();
}

EntriesManager::~EntriesManager(void) {
	deleteVector(_entries.activeEntries);
	deleteVector(_entries.inactiveEntries);
	while(!_entriesHist.empty()) {
		deleteVector(_entriesHist.top().activeEntries);
		deleteVector(_entriesHist.top().inactiveEntries);
		_entriesHist.pop();
	}
	while(!_entriesRedo.empty()) {
		deleteVector(_entriesRedo.top().activeEntries);
		deleteVector(_entriesRedo.top().inactiveEntries);
		_entriesRedo.pop();
	}
	//delete _instance;
}
void EntriesManager::updateFile() {
	_file->updateFromVector(getAllEntries());//DEPENDENCY ON FILEMANAGER
	return;
}
vector<Entry*> EntriesManager::getAllEntries() {//merges the active and inactive entries
	vector<Entry*> tempVector;//(_entries.activeEntries);
	tempVector.insert(tempVector.end(), _entries.activeEntries.begin(),_entries.activeEntries.end());
	tempVector.insert(tempVector.end(),_entries.inactiveEntries.begin(), _entries.inactiveEntries.end());
	//sort(tempVector.begin(),tempVector.end(), CommonUtils::greater);
	return tempVector;
}
void EntriesManager::clearRedoStack() {
	while(!_entriesRedo.empty()) {
		deleteVector(_entriesRedo.top().activeEntries);
		deleteVector(_entriesRedo.top().inactiveEntries);
		_entriesRedo.pop();
	}
}
void EntriesManager::clearOverflowUndo() {
	if(_entriesHist.size() > 10) {
		stack<ENTRIES> temp;
		for(int i=0; i<10; i++) {
			temp.push(_entriesHist.top());
			_entriesHist.pop();
		}
		while(!_entriesHist.empty()) {
			deleteVector(_entriesHist.top().activeEntries);
			deleteVector(_entriesHist.top().inactiveEntries);
			_entriesHist.pop();
		}
		while(!temp.empty()) {
			_entriesHist.push(temp.top());
			temp.pop();
		}
	}
}
void EntriesManager::generateNewVector() {//updates the file and generates a new vector set of pointers
	updateFile();
	clearRedoStack();
	_entriesHist.push(_entries);
	clearOverflowUndo();//function does nth unless stack of >10
	_entries.activeEntries.clear();
	_entries.inactiveEntries.clear();
	vector<Entry*> tempVector =_file->getEntries();//generates new vector//DEPENDENCY ON FILEMANAGER
	_entries.activeEntries.assign(tempVector.begin(), tempVector.begin()+_entries.currentDisplayIndex);
	tempVector.erase(tempVector.begin(), tempVector.begin()+_entries.currentDisplayIndex);
	_entries.inactiveEntries.assign(tempVector.begin(), tempVector.end());
	_entries.newEntry=NULL;//remove newEntry
	_entries.conflictVector.clear();//clear conflict vector
	return;
}
bool EntriesManager::guiEdit(int row, int col, QVariant data) {
	generateNewVector();
	switch(col) {
	case 0:
		_entries.activeEntries[row]->setName(data.toString().toStdString());
		break;
	case 1:
		_entries.activeEntries[row]->setStartDate(data.toDate());
		_entries.activeEntries[row]->setStartTime(data.toTime());
		break;
	case 2:
		_entries.activeEntries[row]->setEndDate(data.toDate());
		_entries.activeEntries[row]->setEndTime(data.toTime());
		break;
	case 3:
		_entries.activeEntries[row]->setDone();
		break;
	}
	updateFile();
	return true;
}
CommonUtils::ReturnStatus EntriesManager::sendOutputMessage(string messageDisplayed, MSG_TYPE cmd) {
	char buffer[99999];
	CommonUtils::ReturnStatus output;

	switch (cmd){
		case MSG_IS_EMPTY:
			sprintf_s(buffer, "%s is empty", messageDisplayed.c_str());
			break;
		case MSG_INVALID:// failure in undo, edit and delete function
			sprintf_s(buffer, "%s is invalid", messageDisplayed.c_str());
			break;
		case CONFLICT_ADD:
			sprintf_s(buffer, "%s has conflicts!", messageDisplayed.c_str());
			break;
		case SUCCESS_ADD:
			sprintf_s(buffer, "%s was added", messageDisplayed.c_str());
			break;
		case SUCCESS_DISPLAY:
			sprintf_s(buffer, "%s was searched", messageDisplayed.c_str());
			break;
		case SUCCESS_GENERAL:
		case SUCCESS_SEARCH:
			sprintf_s(buffer, "%s was searched", messageDisplayed.c_str());
			break;
		case SUCCESS_DELETE:
			sprintf_s(buffer, "%s was deleted", messageDisplayed.c_str());
			break;
		case SUCCESS_EDIT:
			sprintf_s(buffer, "%s was edited", messageDisplayed.c_str());
			break;
		case SUCCESS_SORT:
			sprintf_s(buffer, "%s was sorted", messageDisplayed.c_str());
			break;
		case SUCCESS_UNDO:
			sprintf_s(buffer, "%s was undone", messageDisplayed.c_str());
			break;
		case SUCCESS_CLEAR:
			sprintf_s(buffer, "%s was Cleared", messageDisplayed.c_str());
			break;
		case SUCCESS_COMPLETED:
			sprintf_s(buffer, "%s was completed", messageDisplayed.c_str());
			break;
		case SEARCH_NO_ITEMS:
			sprintf_s(buffer, "No items that fufil search criteria: %s", messageDisplayed.c_str());
			break;
	}
	output.statusMsg=buffer;
	output.displayMsg=printVectorToString();
	return output;
}
void EntriesManager::updateCurrentDisplayIndex() {
	_entries.currentDisplayIndex = _entries.activeEntries.size();
	return;
}
void EntriesManager::resetSearchAttributes() {
	_entries.searchDate = QDate();//reset search strings
	_entries.searchLabel = "";
	_entries.newEntry=NULL;//remove newEntry
	_entries.conflictVector.clear();//clear conflict vector
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
}
void EntriesManager::resetView() {
	_entries.activeEntries=getAllEntries();
	_entries.inactiveEntries.clear();
	filterStatus();
	updateCurrentDisplayIndex();
	resetSearchAttributes();
}
CommonUtils::ReturnStatus EntriesManager::addCommand(Entry* newEntry) {
	assert(newEntry != NULL);
	qxtLog->info(QList<QVariant>() << "addCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "addCommand" << "\n");
	
	generateNewVector();
	resetView();
	_entries.activeEntries.push_back(newEntry);
	updateCurrentDisplayIndex();
	updateFile();
	string messageDisplayed = newEntry->getName();
	_entries.newEntry= newEntry;//set newEntry
	_entries.conflictVector=getConflict(newEntry);//set conflictVector
	return sendOutputMessage(messageDisplayed, SUCCESS_ADD); 
}
CommonUtils::ReturnStatus EntriesManager::deleteCommand(int index) {
	qxtLog->info(QList<QVariant>() << "deleteCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "deleteCommand" << "\n");
	
	if(index-1 >= (_entries.currentDisplayIndex) || index <=0 ) {//invalid index
		throw BotException(BotException::EXCEPTION_INVALID_INDEX);
	}
	generateNewVector();
	Entry* removedEntry(_entries.activeEntries[index-1]);
	_entries.activeEntries.erase(_entries.activeEntries.begin()+index-1);
	updateCurrentDisplayIndex();
	updateFile();
	string messageDisplayed = removedEntry->getName().c_str();
	return sendOutputMessage(messageDisplayed, SUCCESS_DELETE);  
}
vector<vector<CommonUtils::ReturnString>> EntriesManager::printVectorToString() {
	CommonUtils::ReturnStatus output;
	switch(_entries.currentDisplayFormat) {
	case DISPLAY_DEFAULT:
	default:
		defaultSort();
		output.displayMsg = getDefaultString();//printVectorToString(_entries.activeEntries);
		break;
	case DISPLAY_SEARCH:
		sortByDate();
		output.displayMsg = getSearchString();
		break;
	case DISPLAY_SEARCH_DATE:
		sortByDate();
		output.displayMsg = getSearchDateString();
		break;
	}
	return output.displayMsg;
}
void EntriesManager::showAll() {
	_entries.activeEntries=getAllEntries();
	_entries.inactiveEntries.clear();
	updateCurrentDisplayIndex();
	resetSearchAttributes();
}
void EntriesManager::convertTaskToEvent(Entry* &targetEntry) {
	assert(targetEntry->getEntryType() == CommonUtils::ENTRY_TYPE_TASK);
	Entry* newEntry = new Event(targetEntry);
	delete targetEntry;
	targetEntry = newEntry;
}
CommonUtils::ReturnStatus EntriesManager::displayCommand(bool type) {
	if(type == true){
		showAll();
	} else {
		resetView();
	}
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
	string messageDisplayed = "Display ALL";
	return sendOutputMessage(messageDisplayed, SUCCESS_DISPLAY); 
}

CommonUtils::ReturnStatus EntriesManager::editCommand(int index, vector<string> entryVector) {
	qxtLog->info(QList<QVariant>() << "editCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "editCommand" << "\n");
	if(index-1 >= (_entries.currentDisplayIndex) || index <=0 ) {//invalid index
		throw BotException(BotException::EXCEPTION_INVALID_INDEX);
	}
	generateNewVector();
	assert(entryVector.size()==5);
	Entry* targetEntry = _entries.activeEntries[index-1];
	_entries.newEntry = targetEntry;
	if(entryVector[0] != STRING_NULL){
		targetEntry->setName(entryVector[0]);
	}
	//for date and time, assume checking is done in tokeniser
	if(entryVector[1] != STRING_NULL) {
		if(targetEntry->getEntryType() == ENTRY_TYPE_TASK){
			convertTaskToEvent(targetEntry);
			targetEntry->setStartTime(QTime::fromString(QString::fromStdString(entryVector[1]), CommonUtils::FORMAT_TIME));
			targetEntry->setStartDate(targetEntry->getEndDate());
			_entries.newEntry = targetEntry;
			_entries.activeEntries[index-1] = targetEntry;
		} else {
			targetEntry->setStartTime(QTime::fromString(QString::fromStdString(entryVector[1]), CommonUtils::FORMAT_TIME));
		}
	}
	if(entryVector[2] != STRING_NULL) {
		if(targetEntry->getEntryType() == ENTRY_TYPE_TASK) {
			convertTaskToEvent(targetEntry);
			targetEntry->setStartTime(CommonUtils::TIME_MIDNIGHT);
			targetEntry->setStartDate((QDate::fromString(QString::fromStdString(entryVector[2]), CommonUtils::FORMAT_DATE)));
			_entries.newEntry = targetEntry;
			_entries.activeEntries[index-1] = targetEntry;
		} else {
			targetEntry->setStartDate(QDate::fromString(QString::fromStdString(entryVector[2]), CommonUtils::FORMAT_DATE));
		}
	}
	if(entryVector[3] != STRING_NULL) {
		targetEntry->setEndTime(QTime::fromString(QString::fromStdString(entryVector[3]), CommonUtils::FORMAT_TIME));
	}
	if(entryVector[4] != STRING_NULL) {
		targetEntry->setEndDate(QDate::fromString(QString::fromStdString(entryVector[4]), CommonUtils::FORMAT_DATE));
	}
	//sortByDate();
	string messageDisplayed =  _entries.activeEntries[index-1]->getName().c_str();
	return sendOutputMessage(messageDisplayed, SUCCESS_EDIT); 
}

CommonUtils::ReturnStatus EntriesManager::sortCommand(){
	//generateNewVector();
	sortByDate();
	updateFile();

	string messageDisplayed = "ALL";
	return sendOutputMessage(messageDisplayed, SUCCESS_SORT); 
}
void EntriesManager::deleteVector(vector<Entry*> &vect) {
	for(int i=0; i< vect.size(); i++) {
		delete vect[i];
		vect[i]=NULL;
	}
	vect.clear();
}
CommonUtils::ReturnStatus EntriesManager::undoCommand() {// delete the current vector, take old vector, update
	qxtLog->info(QList<QVariant>() << "undoCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "undoCommand" << "\n");
	if(_entriesHist.size()==0){
		string messageDisplayed = "Undo Stack";
		throw BotException(BotException::EXCEPTION_UNDO_INVALID);
		return sendOutputMessage(messageDisplayed, MSG_INVALID);
	}
	_entriesRedo.push(_entries);
	//deleteVector(_entries.activeEntries);
	//deleteVector(_entries.inactiveEntries);
	_entries = _entriesHist.top();
	_entriesHist.pop();
	updateCurrentDisplayIndex();
	updateFile();
	string messageDisplayed = "Last command";
	return sendOutputMessage(messageDisplayed, SUCCESS_UNDO); 
}
CommonUtils::ReturnStatus EntriesManager::redoCommand() {// delete the current vector, take old vector, update
	qxtLog->info(QList<QVariant>() << "redoCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "redoCommand" << "\n");
	if(_entriesRedo.size()==0){
		string messageDisplayed = "Redo Stack";
		throw BotException(BotException::EXCEPTION_REDO_INVALID);
		return sendOutputMessage(messageDisplayed, MSG_INVALID);
	}
	//_entriesRedo.push(_entries);
	//deleteVector(_entries.activeEntries);
	//deleteVector(_entries.inactiveEntries);
	//generateNewVector();
	_entriesHist.push(_entries);
	_entries = _entriesRedo.top();
	_entriesRedo.pop();
	updateCurrentDisplayIndex();
	updateFile();
	string messageDisplayed = "Last command";
	return sendOutputMessage(messageDisplayed, SUCCESS_UNDO); 
}
CommonUtils::ReturnStatus EntriesManager::clearCommand() {
	qxtLog->info(QList<QVariant>() << "clearCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "clearCommand" << "\n");
	generateNewVector();
	deleteVector(_entries.activeEntries);
	deleteVector(_entries.inactiveEntries);
	updateCurrentDisplayIndex();
	updateFile();
	string messageDisplayed = "All";
	return sendOutputMessage(messageDisplayed, SUCCESS_CLEAR); 
}
vector<Entry*> EntriesManager::getConflict(Entry* newEntry) {
	vector<Entry*> temp = (getAllEntries());
	vector<Entry*> found;
	vector<Entry*> notFound;
	for(int i=0; i<temp.size(); i++) {
		if(temp[i]->isConflict(newEntry) && temp[i]!=newEntry) {//DEPENDENCY ON EVENTS
			found.push_back(temp[i]);//newEntry itself not included
		} else {
			notFound.push_back(temp[i]);
		}
	}
	return found;
}

CommonUtils::ReturnStatus EntriesManager::setDoneCommand(int index) {
	qxtLog->info(QList<QVariant>() << "setDoneCommand" << "\n");
	qxtLog->debug(QList<QVariant>() << "setDoneCommand" << "\n");
	if(index-1 >= (_entries.currentDisplayIndex) || index <=0 ) {//invalid index
		throw BotException(BotException::EXCEPTION_INVALID_INDEX);
	}
	generateNewVector();
	_entries.activeEntries[index-1]->setDone();
	updateFile();
	filterStatus();
	string messageDisplayed = _entries.activeEntries[index-1]->getName();
	
	return sendOutputMessage(messageDisplayed, SUCCESS_COMPLETED); 
}
void EntriesManager::sortByDate() {
	sort(_entries.activeEntries.begin(), _entries.activeEntries.end(), CommonUtils::greater);//DEPENDENCY ON COMMONUILS
	//updateFile();
}
void EntriesManager::defaultSort() {
	vector<Entry*> past;
	vector<Entry*> today;
	vector<Entry*> tomorrow;
	vector<Entry*> future;
	//filter done not done
	for(int i=0; i<_entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->isPast()) {//if past
			past.push_back(_entries.activeEntries[i]);
		}else if(_entries.activeEntries[i]->isOccuring() || _entries.activeEntries[i]->isFloat()) {//occurs today
			today.push_back(_entries.activeEntries[i]);
		}else if(_entries.activeEntries[i]->isOccuring(QDate::currentDate().addDays(1))) {//occurs tomorrow
			tomorrow.push_back(_entries.activeEntries[i]);
		} else {
			future.push_back(_entries.activeEntries[i]);
		}
	}
	sort(past.begin(), past.end(), CommonUtils::greater);
	sort(today.begin(), today.end(), CommonUtils::greater);
	sort(tomorrow.begin(), tomorrow.end(), CommonUtils::greater);
	sort(future.begin(), future.end(), CommonUtils::greater);
	_entries.activeEntries.clear();
	_entries.activeEntries.insert(_entries.activeEntries.end(), past.begin(), past.end());
	_entries.activeEntries.insert(_entries.activeEntries.end(), today.begin(), today.end());
	_entries.activeEntries.insert(_entries.activeEntries.end(), tomorrow.begin(), tomorrow.end());
	_entries.activeEntries.insert(_entries.activeEntries.end(), future.begin(), future.end());
}
CommonUtils::ReturnCount EntriesManager::getCount(){
	CommonUtils::ReturnCount entriesCount={0,0,0,0,0};
	vector<Entry*> temp= getAllEntries();
	for(int i=0; i<temp.size(); i++) {
		if(temp[i]->getStatus() == false) {
			if(temp[i]->isPast()){
				entriesCount.numOverdue++;
			}else if(temp[i]->isOccuring() || temp[i]->isFloat() ) {
				entriesCount.numToday++;
			} else{
				entriesCount.numFuture++;
			}
		}
	}
	for(int i=0; i<temp.size(); i++){
		if(temp[i]->getStatus()==false) {
			if(temp[i]->getEntryType() == CommonUtils::ENTRY_TYPE_EVENT)
				entriesCount.numEvents++;
			else
				entriesCount.numTasks++;
		}
	}
	return entriesCount;
}
bool EntriesManager::isTask(Entry* entry) {
	return entry->getEntryType() == CommonUtils::ENTRY_TYPE_TASK;
}
void EntriesManager::setFormat(Entry* entry, CommonUtils::ReturnString &entryString) {
	if(entry->getStatus() == true) {
		entryString.format=CommonUtils::DISPLAY_FORMAT_COMPLETED;
	} else if(entry == _entries.newEntry){
		entryString.format=CommonUtils::DISPLAY_FORMAT_NEW;
	} else if(find(_entries.conflictVector.begin(),_entries.conflictVector.end(),entry) != _entries.conflictVector.end()) {//if found in conflict
		entryString.format=CommonUtils::DISPLAY_FORMAT_CLASH;
	} else {
		entryString.format=CommonUtils::DISPLAY_FORMAT_DEFAULT;
	}
}
string EntriesManager::printEventDateTime(Entry* entry) {
	return entry->getStartDate().toString("[ddd, dd/MM ").toStdString() + entry->getStartTime().toString("hh:mmap -").toStdString() +entry->getEndDate().toString("ddd, dd/MM ").toStdString() +entry->getEndTime().toString("hh:mmap]").toStdString();
}
string EntriesManager::printTaskDateTime(Entry* entry) {
	return entry->getEndDate().toString("by [ddd, dd/MM ").toStdString() + entry->getEndTime().toString("hh:mmap]").toStdString();
}
CommonUtils::ReturnString EntriesManager::getPastString(int i) {
	CommonUtils::ReturnString entryString;
	entryString.entry.first= to_string(i+1) +". "+ _entries.activeEntries[i]->getName();
	if(isTask(_entries.activeEntries[i])){
		entryString.entry.second = printTaskDateTime(_entries.activeEntries[i]);
	}else{
		entryString.entry.second = printEventDateTime(_entries.activeEntries[i]);
	}
	setFormat(_entries.activeEntries[i], entryString);
	return entryString;
}
string EntriesManager::printTodayTaskDateTime(Entry* entry) {
	return entry->getEndTime().toString("by [hh:mmap]").toStdString();
}
string EntriesManager::printTodayEventDateTime(Entry* entry) {
	return entry->getStartTime().toString("[hh:mmap -").toStdString() + entry->getEndTime().toString("hh:mmap]").toStdString();
}
string EntriesManager::printTodaySpanningEventDateTime(Entry* entry) {
	QDate startDate = entry->getStartDate();
	string startDateString;
	if(startDate == QDate::currentDate()) {
		startDateString = "[Today ";
	} else {
		startDateString = startDate.toString("[ddd, dd/MM ").toStdString();
	}
	QDate endDate = entry->getEndDate();
	string endDateString;
	if(endDate == QDate::currentDate()) {
		endDateString = "Today ";
	} else {
		endDateString = endDate.toString("ddd, dd/MM ").toStdString();
	}
	return startDateString + entry->getStartTime().toString("hh:mmap -").toStdString() + endDateString + entry->getEndTime().toString("hh:mmap]").toStdString();
}
CommonUtils::ReturnString EntriesManager::getTodayString(int i) {
	CommonUtils::ReturnString entryString;
	entryString.entry.first=to_string(i+1) +". "+_entries.activeEntries[i]->getName();
	if(_entries.activeEntries[i]->getEntryType() == CommonUtils::ENTRY_TYPE_TASK){
		entryString.entry.second = printTodayTaskDateTime(_entries.activeEntries[i]);
	}else{
		if(_entries.activeEntries[i]->isSpanning()){
			entryString.entry.second =  printTodaySpanningEventDateTime(_entries.activeEntries[i]);
		}else {
			entryString.entry.second =  printTodayEventDateTime(_entries.activeEntries[i]);
		}
	}
	setFormat(_entries.activeEntries[i], entryString);
	return entryString;
}
void EntriesManager::setDefaultDisplayHeader(vector<CommonUtils::ReturnString>& past,vector<CommonUtils::ReturnString>& today,vector<CommonUtils::ReturnString>& tomorrow,vector<CommonUtils::ReturnString>& future){
	CommonUtils::ReturnString pastHeader;
	pastHeader.entry.first= "OverDue:";
	pastHeader.entry.second="";
	pastHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	past.push_back(pastHeader);	
	CommonUtils::ReturnString todayHeader;
	todayHeader.entry.first= "Today:";
	todayHeader.entry.second= QDate::currentDate().toString("ddd, dd/MM").toStdString();
	todayHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	today.push_back(todayHeader);
	CommonUtils::ReturnString tomorrowHeader;
	tomorrowHeader.entry.first= "Tomorrow:";
	tomorrowHeader.entry.second=QDate::currentDate().addDays(1).toString("ddd, dd/MM").toStdString();
	tomorrowHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	tomorrow.push_back(tomorrowHeader);
	CommonUtils::ReturnString futureHeader;
	futureHeader.entry.first= "Future:";
	futureHeader.entry.second="";
	futureHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	future.push_back(futureHeader);
}
vector<vector<CommonUtils::ReturnString>> EntriesManager::getDefaultString() {
	vector<vector<CommonUtils::ReturnString>> output;
	vector<CommonUtils::ReturnString> past;
	vector<CommonUtils::ReturnString> today;
	vector<CommonUtils::ReturnString> tomorrow;	
	vector<CommonUtils::ReturnString> future;
	setDefaultDisplayHeader(past, today, tomorrow, future);
	for(int i=0; i<_entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->isPast()) {//if past
			past.push_back(getPastString(i));
		}else if(_entries.activeEntries[i]->isOccuring() || _entries.activeEntries[i]->isFloat()) {//occurs today or is Float
			today.push_back(getTodayString(i));
		}else if(_entries.activeEntries[i]->isOccuring(QDate::currentDate().addDays(1))) {//occurs tomorrow
			tomorrow.push_back(getTodayString(i));
		} else {
			future.push_back(getPastString(i));
		}
	}
	if(past.size() >1) {
		output.push_back(past);
	}
	if(today.size() ==1) {
		CommonUtils::ReturnString emptyString;
		emptyString.entry.first = "~No Entries for Today~";
		emptyString.entry.second = "";
		today.push_back(emptyString);
	}	
	if(tomorrow.size() ==1) {
		CommonUtils::ReturnString emptyString;
		emptyString.entry.first = "~No Entries for Tomorrow~";
		emptyString.entry.second = "";
		tomorrow.push_back(emptyString);
	}	
	if(future.size() ==1) {
		CommonUtils::ReturnString emptyString;
		emptyString.entry.first = "~No Entries~";
		emptyString.entry.second = "";
		future.push_back(emptyString);
	}
	
	output.push_back(today);
	output.push_back(tomorrow);
	output.push_back(future);
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
	return output;
}
void EntriesManager::setSearchDisplayHeader(vector<CommonUtils::ReturnString> &search) {
	CommonUtils::ReturnString searchHeader;
	searchHeader.entry.first= "Search " + _entries.searchLabel + ":" ;
	searchHeader.entry.second="";
	searchHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	search.push_back(searchHeader);
}
vector<vector<CommonUtils::ReturnString>> EntriesManager::getSearchString() {
	vector<vector<CommonUtils::ReturnString>> output;
	vector<CommonUtils::ReturnString> search;
	setSearchDisplayHeader(search);
	for(int i=0; i<_entries.activeEntries.size(); i++) {
		search.push_back(getPastString(i));
	}
	if(search.size() ==1) {
		CommonUtils::ReturnString emptyString;
		emptyString.entry.first = "~No entries match Search Criteria~";
		emptyString.entry.second = "";
		search.push_back(emptyString);
	}
	output.push_back(search);
	_entries.currentDisplayFormat= DISPLAY_SEARCH;
	return output;
}
vector<vector<CommonUtils::ReturnString>> EntriesManager::getSearchDateString() {
	vector<vector<CommonUtils::ReturnString>> output;
	vector<CommonUtils::ReturnString> searchDate;
	CommonUtils::ReturnString searchDateHeader;
	searchDateHeader.entry.first= "Date Searched:";
	searchDateHeader.entry.second= _entries.searchDate.toString("ddd, dd/MM").toStdString();
	searchDateHeader.format = CommonUtils::DISPLAY_FORMAT_DEFAULT;
	searchDate.push_back(searchDateHeader);
	for(int i=0; i<_entries.activeEntries.size(); i++) {
		searchDate.push_back(getPastString(i));
	}
	if(searchDate.size() ==1) {
		CommonUtils::ReturnString emptyString;
		emptyString.entry.first = "~No entries match Search Criteria~";
		emptyString.entry.second = "";
		searchDate.push_back(emptyString);
	}
	output.push_back(searchDate);
	_entries.currentDisplayFormat=DISPLAY_SEARCH_DATE;
	return output;
}
//search functions below/////////////////////////////////////////////////////////////////////////////////////
void EntriesManager::updateFoundEntries(const vector<Entry*> &found,const vector<Entry*> &notFound) {
	_entries.activeEntries.clear();
	_entries.activeEntries.insert(_entries.activeEntries.end(), found.begin(), found.end());
	_entries.inactiveEntries.insert(_entries.inactiveEntries.end(), notFound.begin(), notFound.end());
	updateCurrentDisplayIndex();
}
void EntriesManager::splitVector(string target, vector<Entry*> &found, vector<Entry*> &notFound, int searchType) {
	istringstream searchString(CommonUtils::toLower(target));
	string targetWord;
	if(searchType==0) {//search word by word
		notFound.clear();
		found.clear();
		notFound = _entries.activeEntries;//assigns the elements of activeEntries into not found
		while(searchString>>targetWord) {//logic error in this portion
			//found.clear();
			for(int i=0; i< notFound.size(); i++) {
				if(CommonUtils::toLower(notFound[i]->getSearchString()).find(targetWord) != string::npos) {
					found.push_back(notFound[i]);
					notFound.erase(notFound.begin() + i);//erase the found item from notFound
					//reduce index by 1
					i--;
				} else {
					//do nothing
				}
			}
		}
	} else {//search entire target string
		for(int i=0; i< _entries.activeEntries.size(); i++) {
			if(CommonUtils::toLower(_entries.activeEntries[i]->getSearchString()).find(CommonUtils::toLower(target)) != string::npos) {
				found.push_back(_entries.activeEntries[i]);
			} else {
				notFound.push_back(_entries.activeEntries[i]);
			}
		}
	}
	updateFoundEntries(found, notFound);
}
CommonUtils::ReturnStatus EntriesManager::searchCommand(string target, int searchType) {
	qxtLog->info(QList<QVariant>() << "searchCommand" << searchType << "\n");
	qxtLog->debug(QList<QVariant>() << "searchCommand" << searchType << "\n");
	_entries.searchLabel += " " + target;
	//generateNewVector();
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVector(target, found, notFound, searchType);
	_entries.currentDisplayFormat=DISPLAY_SEARCH;
	string messageDisplayed = target;
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH);
}
void EntriesManager::splitVectorTask(vector<Entry*> &found, vector<Entry*> &notFound) {
	for(int i=0; i< _entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->getEntryType() == Task::TYPE_ENTRY) {
			found.push_back(_entries.activeEntries[i]);
		} else {
			notFound.push_back(_entries.activeEntries[i]);
		}
	}//classified them into tasks and not tasks
}
CommonUtils::ReturnStatus EntriesManager::searchTasks() {
	qxtLog->info(QList<QVariant>() << "searchTasks" << "\n");
	qxtLog->debug(QList<QVariant>() << "searchTasks" << "\n");
	//generateNewVector();
	_entries.searchLabel += " " + ENTRY_TYPE_TASK;
	sortByDate();//sorts all by date
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVectorTask(found, notFound);
	updateFoundEntries(found, notFound);
	_entries.currentDisplayFormat = DISPLAY_SEARCH;
	string messageDisplayed = ENTRY_TYPE_TASK;
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH); // 7 is a successful searchCommand
}
void EntriesManager::splitVectorEvent(vector<Entry*> &found, vector<Entry*> &notFound) {
	for(int i=0; i< _entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->getEntryType() == Event::TYPE_ENTRY) {
			found.push_back(_entries.activeEntries[i]);
		} else {
			notFound.push_back(_entries.activeEntries[i]);
		}
	}//classified them into tasks and not tasks
}
CommonUtils::ReturnStatus EntriesManager::searchEvents() {
	qxtLog->info(QList<QVariant>() << "searchEvents" << "\n");
	qxtLog->debug(QList<QVariant>() << "searchEvents" << "\n");
	//generateNewVector();
	_entries.searchLabel += " " + ENTRY_TYPE_EVENT;
	sortByDate();//sorts all by date
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVectorEvent(found, notFound);
	updateFoundEntries(found, notFound);
	_entries.currentDisplayFormat = DISPLAY_SEARCH;
	string messageDisplayed = ENTRY_TYPE_EVENT;// outputStream.str();
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH); // 7 is a successful searchCommand
}
void EntriesManager::splitVectorWeek(vector<Entry*> &found, vector<Entry*> &notFound) {
	for(int i=0; i< _entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->getEndDate()>= QDate::currentDate() && _entries.activeEntries[i]->getEndDate() <QDate::currentDate().addDays(7) ) {
			found.push_back(_entries.activeEntries[i]);
		} else {
			notFound.push_back(_entries.activeEntries[i]);
		}
	}//classified them into tasks and not tasks
}
CommonUtils::ReturnStatus EntriesManager::searchWeek() {
	qxtLog->info(QList<QVariant>() << "searchWeek" << "\n");
	qxtLog->debug(QList<QVariant>() << "searchWeek" << "\n");
	//generateNewVector();
	sortByDate();//sorts all by date
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVectorWeek(found, notFound);
	updateFoundEntries(found, notFound);
	_entries.currentDisplayFormat = DISPLAY_SEARCH;
	string messageDisplayed = "Items for upcoming week";// outputStream.str();
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH); // 7 is a successful searchCommand
}
void EntriesManager::splitVectorDay(QDate target, vector<Entry*> &found, vector<Entry*> &notFound, int searchType) {
	for(int i=0; i< _entries.activeEntries.size(); i++) {
		if(searchType == 0) {//search exact date
			if(_entries.activeEntries[i]->isOccuring( target) ) {
				found.push_back(_entries.activeEntries[i]);
			} else {
				notFound.push_back(_entries.activeEntries[i]);
			}
		} else if(searchType == 1) {//needs to be done by target date or occurs on target date
			if(_entries.activeEntries[i]->isPast(QDateTime(target)) || _entries.activeEntries[i]->isOccuring( target) ) {
				found.push_back(_entries.activeEntries[i]);
			} else {
				notFound.push_back(_entries.activeEntries[i]);
			}
		}
	}//classified them into tasks and not tasks
}
CommonUtils::ReturnStatus EntriesManager::searchDay(QDate target, int searchType) {
	qxtLog->info(QList<QVariant>() << "searchDay" << searchType << "\n");
	qxtLog->debug(QList<QVariant>() << "searchDay" << searchType << "\n");
	//generateNewVector();
	//sortByDate();//sorts all by date
	_entries.searchDate = target;
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVectorDay(target, found, notFound, searchType);
	updateFoundEntries(found, notFound);
	_entries.currentDisplayFormat = DISPLAY_SEARCH_DATE;
	string messageDisplayed = "Items in " + target.toString(CommonUtils::FORMAT_DATE).toStdString();
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH); // 7 is a successful searchCommand
}
void EntriesManager::splitVectorStatus(bool target, vector<Entry*> &found, vector<Entry*> &notFound) {
	for(int i=0; i< _entries.activeEntries.size(); i++) {
		if(_entries.activeEntries[i]->getStatus() == target ) {
			found.push_back(_entries.activeEntries[i]);
		} else {
			notFound.push_back(_entries.activeEntries[i]);
		}
	}//classified them into tasks and not tasks
}
void EntriesManager::filterStatus(bool target) {
	vector<Entry*> found;
	vector<Entry*> notFound;
	splitVectorStatus(target, found, notFound);
	updateFoundEntries(found, notFound);
}
CommonUtils::ReturnStatus EntriesManager::searchStatus(bool target) {
	qxtLog->info(QList<QVariant>() << "searchStatus" << "\n");
	qxtLog->debug(QList<QVariant>() << "searchStatus" << "\n");
	//generateNewVector();
	//searchTasks();
//	sortByDate();//sorts all by date
	filterStatus(target);
	_entries.currentDisplayFormat = DISPLAY_SEARCH;
	string messageDisplayed = ("Complete" ? target == 0 : "Incomplete")+ " Entries";
	if(_entries.currentDisplayIndex==0){
		return sendOutputMessage(messageDisplayed, SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, SUCCESS_SEARCH); // 7 is a successful searchCommand
}
vector<Entry*> EntriesManager::getActive() {
	return _entries.activeEntries;
}
QStringList EntriesManager::getNameVect() {
	QStringList output;
	for(int i=0; i<_entries.activeEntries.size(); i++)
		output << QString::fromStdString(_entries.activeEntries[i]->getName());
	return output;
}
const string EntriesManager::_fileName= "storage.txt";
const string EntriesManager::STRING_NULL = "";
const string EntriesManager::ENTRY_TYPE_TASK = "TASK";
const string EntriesManager::ENTRY_TYPE_EVENT = "EVENT";